#pragma once

#include "Utils.hpp"
#include "Monsters.hpp"
#include <iostream>
#include <string>

namespace MonsterFactory {

  // factory interface
  class IMonsterFactory {
  public:
    virtual IMonster* CreatePhaseOneMonster(int) = 0;
    virtual IMonster* CreatePhaseTwoMonster(int) = 0;
  };

  // animal monster factory
  class AnimalMonsterFactory : public IMonsterFactory {
  public:
    IMonster* CreatePhaseOneMonster(int level = 1);
    IMonster* CreatePhaseTwoMonster(int level = 11);

    static AnimalMonsterFactory* GetInstance() {
      if (instance == NULL)
	instance = new AnimalMonsterFactory();
      return instance;
    }

  private:
    AnimalMonsterFactory(){}
    AnimalMonsterFactory(const AnimalMonsterFactory&) {};
    AnimalMonsterFactory& operator=(const AnimalMonsterFactory&) {}
    static AnimalMonsterFactory* instance;    

    class Garbo
    {
    public:
      ~Garbo()
      {
	if(AnimalMonsterFactory::instance != NULL  )
	  {
	    delete AnimalMonsterFactory::instance;
	    AnimalMonsterFactory::instance = NULL;
	  }
      }
    };
    static Garbo garbo;
  };

  // plant monster factory
  class PlantMonsterFactory : public IMonsterFactory {
  public:
    IMonster* CreatePhaseOneMonster(int level = 1);
    IMonster* CreatePhaseTwoMonster(int level = 11);

    static PlantMonsterFactory* GetInstance() {
      if (instance == NULL)
	instance = new PlantMonsterFactory();
      return instance;
    }

  private:
    PlantMonsterFactory(){}
    PlantMonsterFactory(const PlantMonsterFactory&) {};
    PlantMonsterFactory& operator=(const PlantMonsterFactory&) {}
    static PlantMonsterFactory* instance;    

    class Garbo
    {
    public:
      ~Garbo()
      {
	if(PlantMonsterFactory::instance != NULL  )
	  {
	    delete PlantMonsterFactory::instance;
	    PlantMonsterFactory::instance = NULL;
	  }
      }
    };
    static Garbo garbo;
  };

   // elite monster factory
  class EliteMonsterFactory : public IMonsterFactory {
  public:
    IMonster* CreatePhaseOneMonster(int level = 1);
    IMonster* CreatePhaseTwoMonster(int level = 11);

    static EliteMonsterFactory* GetInstance() {
      if (instance == NULL)
	instance = new EliteMonsterFactory();
      return instance;
    }

  private:
    EliteMonsterFactory(){}
    EliteMonsterFactory(const EliteMonsterFactory&) {};
    EliteMonsterFactory& operator=(const EliteMonsterFactory&) {}
    static EliteMonsterFactory* instance;    

    class Garbo
    {
    public:
      ~Garbo()
      {
	if(EliteMonsterFactory::instance != NULL  )
	  {
	    delete EliteMonsterFactory::instance;
	    EliteMonsterFactory::instance = NULL;
	  }
      }
    };
    static Garbo garbo;
  };
}
